package com.gipson.amc.service.basicdata;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gipson.amc.entity.PageByDataTable;
import com.dsbj.common.msg.ResponseMessage;
import com.gipson.amc.entity.Company;
import com.gipson.amc.entity.PostGroup;
import com.gipson.amc.entity.User;
import com.gipson.amc.mapper.PostGroupMapper;
import com.gipson.amc.model.TreeNode;
import com.gipson.amc.utils.Constants;
import com.gipson.amc.utils.security.ShiroUtils;
import com.gipson.amc.utils.strprocess.ObjectParse;
import org.apache.commons.lang3.StringUtils;
import com.gipson.amc.utils.listprocess.ListProcess;
import com.gipson.amc.utils.strprocess.ArrayUtil;
import com.gipson.amc.utils.strprocess.StrUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.*;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 * 岗位管理 服务实现类
 * </p>
 *
 * @author cjw
 * @since 2020-05-21
 */
@Service
@Transactional
public class PostGroupService extends ServiceImpl<PostGroupMapper, PostGroup> {
	
	@Resource
	private CompanyService companyService;
	
	/**
	 * 根据postNameDim,companyCode模糊查询postGroup列表。
	 * <br><br>该方法的流程为:
	 * <br>1、根据postNameDim,companyCode模糊查询,获得postGroup列表(list_postGroup)。
	 * <br>2、遍历list_postGroup中每个postGroup，查询其包含的子postGroup列表(list_postGroup_sub),并存入list_postGroup_final中。
	 * <br>3、去除list_postGroup_final中的重复项, 并根据postGroup.code升序排序, 最后返回该postGroup列表。
	 *
	 * @param
	 * @return
	 * @author cjw 2020-03-28
	 */
	public List<PostGroup> getPostGroupByPostNameDimByCompanyCode(String postNameDim, String companyCode) {
		/**
		 * 1、根据postNameDim,companyCode模糊查询,获得postGroup列表(list_postGroup)。
		 */
		Wrapper<PostGroup> wrapper = Wrappers.<PostGroup>lambdaQuery()
				.eq(StrUtil.isNotEmpty(companyCode), PostGroup::getCompanyCode, companyCode)
				.like(StrUtil.isNotEmpty(postNameDim), PostGroup::getPostName, postNameDim)
				.orderByAsc(PostGroup::getPostCode);
		List<PostGroup> list_postGroup = baseMapper.selectList(wrapper);
		
		/**
		 * 2、遍历list_postGroup中每个postGroup，查询其包含的子postGroup列表(list_postGroup_sub),并存入list_postGroup_final中。
		 */
		List<PostGroup> list_postGroup_final = new ArrayList<>();
		
		for (PostGroup postGroup : list_postGroup) {
			//根据postGroup.postCode, companyCode模糊查询, 获得list_postGroup_sub。
			wrapper = Wrappers.<PostGroup>lambdaQuery()
					.eq(StrUtil.isNotEmpty(companyCode), PostGroup::getCompanyCode, companyCode)
					.likeRight(PostGroup::getPostCode, postGroup.getPostCode())
					.orderByAsc(PostGroup::getPostCode);
			List<PostGroup> list_postGroup_sub = baseMapper.selectList(wrapper);
			//将list_postGroup_sub存入list_postGroup_final中。
			list_postGroup_final.addAll(list_postGroup_sub);
		}
		
		/**
		 * 3、去除list_postGroup_final中的重复项, 并根据postGroup.code升序排序, 最后返回该postGroup列表。
		 */
		list_postGroup_final = removeDuplicatePostGroup(list_postGroup_final);
		//当前list_postGroup_final已按postGroup.postCode升序排序。
		return list_postGroup_final;
	}
	
	/**
	 * 去除list_authority中的重复项。此处根据postGroup.id判断二者是否重复。
	 *
	 * @param
	 * @return
	 * @author cjw 2020-05-08
	 */
	public static List<PostGroup> removeDuplicatePostGroup(List<PostGroup> list_postGroup) {
		if (list_postGroup == null) {
			return null;
		}
		//mapId的键值对格式为《"id=id_1", null》
		Map<String, Object> mapId = new HashMap<>();
		List<PostGroup> list_postGroup_washed = new ArrayList<>();
		
		for (PostGroup postGroup : list_postGroup) {
			String key = "id=" + postGroup.getId();
			//若mapId中不含有该key
			if (!mapId.containsKey(key)) {
				//将postGroup存入list_postGroup_washed中。
				list_postGroup_washed.add(postGroup);
				//将key存入mapId中。
				mapId.put(key, null);
			}
		}
		return list_postGroup_washed;
	}
	
	/**
	 * 产生输出的postGroup信息。以树状结构输出list_postGroup。
	 *
	 * @param
	 * @return
	 * @author cjw 2020-05-06
	 */
	public static JSONArray generatePostGroup(List<PostGroup> list_postGroup) {
		if (list_postGroup == null) {
			return null;
		}
		//将list_postGroup转为树状结构的数据
		JSONArray json_array = JSONArray.parseArray(JSON.toJSONString(list_postGroup, SerializerFeature.WriteMapNullValue));
		JSONArray json_array2 = ListProcess.listToTree(json_array, "id", "parentId", "children");
		return json_array2;
	}
	
	
	/****
	 * 对外eam获取岗位接口使用wcm
	 * @return
	 */
	public List<PostGroup> getPostByCompanyCode(String companyCode) {
		Wrapper<PostGroup> wrapper = Wrappers.<PostGroup>lambdaQuery()
				.eq(PostGroup::getDelFlag, 0)
				.eq(PostGroup::getCompanyCode, companyCode)
				.orderByAsc(PostGroup::getSort);
		List<PostGroup> list_postGroup = baseMapper.selectList(wrapper);
		return list_postGroup;
	}
	
	
	/**
	 * @param
	 * @return
	 * @description 岗位管理 平铺式分页
	 * @author: xsyuan 2020/5/22 12:55
	 */
	public Page<PostGroup> getPostGroupPage(PostGroup postGroup, PageByDataTable pageByDataTable) {
		Page<PostGroup> page = new Page<PostGroup>().setCurrent(pageByDataTable.getPageindex()).setSize(pageByDataTable.getPagesize());
		QueryWrapper<PostGroup> queryWrapper = new QueryWrapper<PostGroup>()
				.eq(StringUtils.isNotBlank(postGroup.getCompanyCode()), "COMPANY_CODE", postGroup.getCompanyCode())
				.like(StringUtils.isNotBlank(postGroup.getPostCode()), "POST_CODE", postGroup.getPostCode())
				.like(StringUtils.isNotBlank(postGroup.getPostName()), "POST_NAME", postGroup.getPostName())
				.notIn(!ArrayUtil.isEmpty(postGroup.getPostGroupIdNotIn()), "ID", Arrays.asList(postGroup.getPostGroupIdNotIn()));
		baseMapper.selectPage(page, queryWrapper);
		return page;
	}
	
	/**
	 * @param
	 * @return
	 * @description 岗位管理  树形结构
	 * @author: xsyuan 2020/5/22 13:12
	 */
	public List<TreeNode> getTreeData(String companyCode, String postGroupIdNotIn) {
		List<TreeNode> treeList = new ArrayList<>();
		TreeNode rootTree = new TreeNode();
		rootTree.setId("0");
		rootTree.setPId("-1");
		rootTree.setIcon("/static/plugin/ztree/zTreeStyle/img/diy/1_close.png");
		rootTree.setType(0);
		rootTree.setName("全部");
		treeList.add(rootTree);
		List<PostGroup> postGroupList = baseMapper.selectList(new QueryWrapper<PostGroup>()
				.eq(StringUtils.isNotEmpty(companyCode), "COMPANY_CODE", companyCode)
				.notIn(StringUtils.isNoneBlank(postGroupIdNotIn), "ID", Arrays.asList(postGroupIdNotIn.split(","))));
		rootTree.setOpen(true);
		for (PostGroup postGroup : postGroupList) {
			TreeNode treedictData = new TreeNode();
			treedictData.setId(postGroup.getId());
			treedictData.setType(1);
			treedictData.setValue(postGroup.getPostCode());
			treedictData.setPId(StringUtils.isBlank(postGroup.getParentId()) ? rootTree.getId() : postGroup.getParentId());
			treedictData.setName(postGroup.getPostName());
			treedictData.setIcon("/static/imgs/tree/cate.png");
			treeList.add(treedictData);
		}
		return treeList;
	}
	
	public List<PostGroup> getPostGroupsByUserId(String userId) {
		return baseMapper.getPostGroupsByUserId(userId);
	}
	
	;
	
	
	/**
	 * 根据companyCode获取postGroup列表。
	 *
	 * @param
	 * @return
	 * @author cjw 2020-05-23
	 */
	public List<PostGroup> getPostGroupByCompanyCode(String companyCode) {
		Wrapper<PostGroup> wrapper = Wrappers.<PostGroup>lambdaQuery()
				.eq(StrUtil.isNotEmpty(companyCode), PostGroup::getCompanyCode, companyCode)
				.eq(PostGroup::getDelFlag, 0)
				.orderByAsc(PostGroup::getPostCode);
		List<PostGroup> list_postGroup = baseMapper.selectList(wrapper);
		return list_postGroup;
	}
	
	/**
	 * 检查postGroup》检查postCode,postName是否有效。postCode,postName不可重复。
	 * 传入参数: id,postCode,postName,companyCode。
	 *
	 * @param
	 * @return
	 * @author cjw 2020-05-07
	 */
	public ResponseMessage checkPostGroupForPostCodeAndPostName(String id, String postCode, String postName, String companyCode) {
		//若postCode不为空
		if (StrUtil.isNotEmpty(postCode)) {
			//检查postCode是否重复
			Wrapper<PostGroup> wrapper = Wrappers.<PostGroup>lambdaQuery()
					.ne(StrUtil.isNotEmpty(id), PostGroup::getId, id)
					.eq(PostGroup::getPostCode, postCode)
					.eq(StrUtil.isNotEmpty(companyCode), PostGroup::getCompanyCode, companyCode);
			List<PostGroup> postGroupList = baseMapper.selectList(wrapper);
			if (postGroupList.size() > 0) {
				return ResponseMessage.error("岗位编号(postCode)已存在,请重新输入岗位编号!");
			}
		}
		//若postName不为空
		if (StrUtil.isNotEmpty(postName)) {
			//检查postName是否重复
			Wrapper<PostGroup> wrapper = Wrappers.<PostGroup>lambdaQuery()
					.ne(StrUtil.isNotEmpty(id), PostGroup::getId, id)
					.eq(PostGroup::getPostName, postName)
					.eq(StrUtil.isNotEmpty(companyCode), PostGroup::getCompanyCode, companyCode);
			List<PostGroup> postGroupList = baseMapper.selectList(wrapper);
			if (postGroupList.size() > 0) {
				return ResponseMessage.error("岗位名称(postName)已存在,请重新输入岗位名称!");
			}
		}
		//返回成功信息
		return ResponseMessage.ok();
	}
	
	/**
	 * 根据postGroupId获取完整的postGroup信息(包含"联表查询字段")。
	 *
	 * @param
	 * @return
	 * @author cjw 2020-05-12
	 */
	public PostGroup getPostGroupFullById(String postGroupId) {
		PostGroup postGroup = baseMapper.selectById(postGroupId);
		//补充postGroup,为postGroup中的新增字段赋值。
		supplementPostGroup(postGroup);
		return postGroup;
	}
	
	/**
	 * 补充postGroup,为postGroup中的新增字段赋值。
	 *
	 * @param
	 * @return
	 * @author cjw 2020-05-08
	 */
	public PostGroup supplementPostGroup(PostGroup postGroup) {
		if (postGroup == null) {
			return null;
		}
		//companyName
		if (StrUtil.isNotEmpty(postGroup.getCompanyCode())) {
			Company company = companyService.getCompanyByCode(postGroup.getCompanyCode());
			postGroup.setCompanyName(company.getCompanyName());
		}
		//parentPostCode
		if (StrUtil.isNotEmpty(postGroup.getParentId())) {
			PostGroup postGroup_temp = baseMapper.selectById(postGroup.getParentId());
			postGroup.setParentPostCode(postGroup_temp.getPostCode());
			postGroup.setParentPostName(postGroup_temp.getPostName());
		}
		return postGroup;
	}
	
	/**
	 * 根据id强制更新postGroup。若字段值为null,亦更新。
	 *
	 * @param
	 * @return
	 * @author cjw 2020-05-12
	 */
	public String updatePostGroupByIdForcedly(PostGroup postGroup) {
		Wrapper<PostGroup> wrapper = Wrappers.<PostGroup>lambdaUpdate()
				.set(PostGroup::getId, postGroup.getId())
				.set(PostGroup::getCompanyCode, postGroup.getCompanyCode() == null ? "" : postGroup.getCompanyCode())
				.set(PostGroup::getParentId, postGroup.getParentId() == null ? "" : postGroup.getParentId())
				.set(PostGroup::getPostCode, postGroup.getPostCode() == null ? "" : postGroup.getPostCode())
				.set(PostGroup::getPostName, postGroup.getPostName() == null ? "" : postGroup.getPostName())
				.set(PostGroup::getSort, postGroup.getSort() == null ? "" : postGroup.getSort())
				.set(PostGroup::getUpdateTime, postGroup.getUpdateTime() == null ? "" : postGroup.getUpdateTime())
				.set(PostGroup::getUpdateUser, postGroup.getUpdateUser() == null ? "" : postGroup.getUpdateUser())
				.eq(PostGroup::getId, postGroup.getId());
		baseMapper.update(null, wrapper);
		return Constants.SUCCESS;
	}
	
	/**
	 * 根据postGroupId删除postGroup, 若该postGroup下含有子岗位,会被一并删除(该方法为物理删除)。
	 *
	 * @param
	 * @return
	 * @author cjw 2020-05-08
	 */
	public ResponseMessage deletePostGroup(String postGroupId) {
		//根据postGroupId获取对应的postGroup信息
		PostGroup postGroup = baseMapper.selectById(postGroupId);
		if (postGroup == null) {
			return ResponseMessage.error("未找到该postGroupId对应的postGroup信息!,postGroupId=" + postGroupId);
		}
		//删除postGroup.postCode下的所有岗位
		Wrapper<PostGroup> wrapper = Wrappers.<PostGroup>lambdaQuery()
				.likeRight(PostGroup::getPostCode, postGroup.getPostCode())
				.eq(PostGroup::getCompanyCode, postGroup.getCompanyCode());
		baseMapper.delete(wrapper);
		return ResponseMessage.ok();
	}
	
	/**
	 * 存入postGroup信息。该方法包含解析参数,验证参数,存入postGroup信息等步骤。
	 *
	 * @param
	 * @return
	 * @author cjw 2020-06-02
	 */
	public ResponseMessage addPostGroup(PostGroup postGroup) {
		//验证addPostGroup().postGroup变量。
		User user = ShiroUtils.getCurrentUser();
		ResponseMessage validateRsp = validateAddPostGroupParam(postGroup);
		if (!validateRsp.isSuccess()) {
			return validateRsp;
		}
		
		/**
		 * 存入postGroup信息。
		 */
		postGroup.setCreateTime(new Date());
		postGroup.setCreateUser(user.getId());
		save(postGroup);
		return ResponseMessage.ok();
	}
	
	/**
	 * 解析,验证addPostGroup().postGroup变量。
	 *
	 * @param
	 * @return
	 * @author cjw 2020-06-02
	 */
	private ResponseMessage validateAddPostGroupParam(PostGroup postGroup) {
		//解析addPostGroup().postGroup变量。
		if (StringUtils.isBlank(postGroup.getCompanyCode())) {
			return ResponseMessage.error("公司编号不能为空!");
		}
		if (StringUtils.isBlank(postGroup.getPostCode())) {
			return ResponseMessage.error("岗位编号不能为空!");
		}
		if (StringUtils.isBlank(postGroup.getPostName())) {
			return ResponseMessage.error("岗位名称不能为空!");
		}
		postGroup.setCompanyCode(postGroup.getCompanyCode().trim());
		postGroup.setPostCode(postGroup.getPostCode().trim());
		postGroup.setPostName(postGroup.getPostName().trim());
		if (StringUtils.isNotBlank(postGroup.getParentId())) {
			postGroup.setParentId(postGroup.getParentId().trim());
		}
		
		/**
		 * 验证传入的参数是否有效。
		 * 检查postGroup》检查postCode,postName是否有效。postCode,postName不可重复。
		 */
		ResponseMessage responseMessageTemp = checkPostGroupForPostCodeAndPostName(null, postGroup.getPostCode(),
				postGroup.getPostName(), postGroup.getCompanyCode());
		if (!responseMessageTemp.isSuccess()) {
			return responseMessageTemp;
		}
		return ResponseMessage.ok();
	}
	
	/**
	 * 更新postGroup信息。该方法包含解析参数,验证参数,更新postGroup信息等步骤。
	 *
	 * @param
	 * @return
	 * @author cjw 2020-06-02
	 */
	public ResponseMessage updatePostGroup(PostGroup postGroup) {
		//解析传来的参数
		User user = ShiroUtils.getCurrentUser();
		if (StrUtil.isEmpty(postGroup.getId())) {
			return ResponseMessage.error("id为空!");
		}
		if (StrUtil.isEmpty(postGroup.getCompanyCode())) {
			return ResponseMessage.error("companyCode为空!");
		}
		if (StrUtil.isEmpty(postGroup.getPostCode())) {
			return ResponseMessage.error("postCode为空!");
		}
		if (StrUtil.isEmpty(postGroup.getPostName())) {
			return ResponseMessage.error("postName为空!");
		}
		
		/**
		 * 验证传入的参数是否有效。
		 * 检查postGroup》检查postCode,postName是否有效。postCode,postName不可重复。
		 */
		ResponseMessage responseMessageTemp = checkPostGroupForPostCodeAndPostName(postGroup.getId(), postGroup.getPostCode(),
				postGroup.getPostName(), postGroup.getCompanyCode());
		if (!responseMessageTemp.isSuccess()) {
			return responseMessageTemp;
		}
		
		/**
		 * 更新postGroup信息。
		 */
		PostGroup postGroupFinal = getById(postGroup.getId());
		if (postGroupFinal == null) {
			return ResponseMessage.error("未找到id对应的postGroup信息!");
		}
		postGroupFinal.setId(postGroup.getId());
		postGroupFinal.setPostCode(postGroup.getPostCode());
		postGroupFinal.setPostName(postGroup.getPostName());
		postGroupFinal.setParentId(postGroup.getParentId());
		postGroupFinal.setCompanyCode(postGroup.getCompanyCode());
		postGroupFinal.setSort(postGroup.getSort());
		postGroupFinal.setUpdateTime(new Date());
		postGroupFinal.setUpdateUser(user.getId());
		//根据id强制更新postGroup。
		updatePostGroupByIdForcedly(postGroupFinal);
		return ResponseMessage.ok();
	}
	
	/**
	 * 根据postIdList获取postGroup列表,其中postGroup包含完整的信息。
	 *
	 * @param
	 * @return
	 * @author cjw 2020-06-02
	 */
	public List<PostGroup> getPostGroupFullByIdList(List<String> postIdList) {
		if (ArrayUtil.isEmpty(postIdList)) {
			return null;
		}
		
		List<PostGroup> postGroupList = baseMapper.selectBatchIds(postIdList);
		
		//companyName
		List<String> companyCodeList = postGroupList.stream().map(PostGroup::getCompanyCode).distinct().collect(Collectors.toList());
		List<Company> companyList = companyService.getCompanyByCode(companyCodeList);
		Map<String, Company> companyMap = companyList.stream().collect(Collectors.toMap(Company::getCompanyCode, x -> x));
		postGroupList.stream().forEach(x -> {
			//companyName
			x.setCompanyName(companyMap.get(x.getCompanyCode()).getCompanyName());
		});
		
		//parentPostCode, parentPostName
		List<String> parentIdList = postGroupList.stream().map(PostGroup::getParentId).distinct().collect(Collectors.toList());
		List<PostGroup> postGroupParentList = baseMapper.selectBatchIds(parentIdList);
		Map<String, PostGroup> postGroupMap = postGroupParentList.stream().collect(Collectors.toMap(PostGroup::getId, x -> x));
		postGroupList.stream().forEach(x -> {
			//parentPostCode,parentPostName
			x.setParentPostCode(postGroupMap.get(x.getParentId()).getPostCode());
			x.setParentPostName(postGroupMap.get(x.getParentId()).getPostName());
		});
		return postGroupList;
	}
	
	
}
